# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.1069.45.2 -> 1.1069.45.3
#	fs/hugetlbfs/inode.c	1.5     -> 1.6    
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/09/30	kenneth.w.chen@intel.com	1.1069.45.3
# HUGETLBFS: fix mount error paths
# 
# Here is a patch that fixes a rather nasty bug in hugetlbfs.  If root
# tries to mount a hugetlbfs with invalid mount option,
# hugetlbfs_fill_super incorrectly returns error code instead of NULL on
# couple error conditions, causing generic vfs layer to segfault and took
# some semaphore with it, the end result is kernel hang on any subsequent
# file system mount/unmount.  There are some other cases that has memory
# leak upon error conditions.
# --------------------------------------------
#
diff -Nru a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
--- a/fs/hugetlbfs/inode.c	Thu Oct  9 15:20:22 2003
+++ b/fs/hugetlbfs/inode.c	Thu Oct  9 15:20:22 2003
@@ -601,23 +601,21 @@
 {
 	struct inode * inode;
 	struct dentry * root;
-	int ret;
 	struct hugetlbfs_config config;
 	struct hugetlbfs_sb_info *sbinfo;
 
-	sbinfo = kmalloc(sizeof(struct hugetlbfs_sb_info), GFP_KERNEL);
-	if (!sbinfo)
-		return -ENOMEM;
-	sb->u.generic_sbp = sbinfo;
- 
 	config.nr_blocks = -1; /* No limit on size by default. */
 	config.nr_inodes = -1; /* No limit on number of inodes by default. */
 	config.uid = current->fsuid;
 	config.gid = current->fsgid;
 	config.mode = 0755;
-	ret = hugetlbfs_parse_options(data, &config);
-	if (ret)
-		return ret;
+	if (hugetlbfs_parse_options(data, &config))
+		return NULL;
+
+	sbinfo = kmalloc(sizeof(struct hugetlbfs_sb_info), GFP_KERNEL);
+	if (!sbinfo)
+		return NULL;
+	sb->u.generic_sbp = sbinfo;
 
 	spin_lock_init(&sbinfo->stat_lock);
 	sbinfo->max_blocks = config.nr_blocks;
@@ -631,15 +629,18 @@
 	inode = hugetlbfs_get_inode(sb, config.uid, config.gid,
 				S_IFDIR | config.mode, 0);
 	if (!inode)
-		return NULL;
+		goto out_free;
 
 	root = d_alloc_root(inode);
 	if (!root) {
 		iput(inode);
-		return NULL;
+		goto out_free;
 	}
 	sb->s_root = root;
 	return sb;
+out_free:
+	kfree(sbinfo);
+	return NULL;
 }
 
 static DECLARE_FSTYPE(hugetlbfs_fs_type, "hugetlbfs", hugetlbfs_fill_super, FS_LITTER);